using Microsoft.Extensions.Logging;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;

namespace JGSY.CMS.LowCode.Platform.Infrastructure.Services.Notification
{
    /// <summary>
    /// 腾讯云短信服务提供商
    /// 支持腾讯云SMS服务
    /// </summary>
    public class TencentSmsProvider : ISmsProvider, IDisposable
    {
        public string Name => "腾讯云短信";

        public bool IsConfigured => !string.IsNullOrEmpty(_settings.SecretId) &&
                                   !string.IsNullOrEmpty(_settings.SecretKey) &&
                                   !string.IsNullOrEmpty(_settings.SdkAppId);

        private readonly TencentSmsSettings _settings;
        private readonly ILogger _logger;
        private readonly HttpClient _httpClient;
        private const string TENCENT_SMS_ENDPOINT = "https://sms.{0}.tencentcloudapi.com/";
        private const string SERVICE = "sms";
        private const string VERSION = "2021-01-11";

        public TencentSmsProvider(TencentSmsSettings settings, ILogger logger)
        {
            _settings = settings ?? throw new ArgumentNullException(nameof(settings));
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));
            _httpClient = new HttpClient
            {
                Timeout = TimeSpan.FromSeconds(30)
            };
        }

        /// <summary>
        /// 发送普通短信
        /// </summary>
        public async Task<SmsSendResult> SendAsync(SmsMessage message)
        {
            if (!IsConfigured)
            {
                return new SmsSendResult
                {
                    Success = false,
                    ErrorMessage = "腾讯云短信提供商未正确配置",
                    SentAt = DateTime.UtcNow,
                    Provider = Name
                };
            }

            try
            {
                var requestPayload = BuildSendSmsPayload(message);
                var requestUrl = string.Format(TENCENT_SMS_ENDPOINT, _settings.Region);
                
                var startTime = DateTime.UtcNow;
                var response = await SendRequest(requestUrl, "SendSms", requestPayload);
                var endTime = DateTime.UtcNow;

                if (response.Success)
                {
                    _logger.LogDebug(
                        "腾讯云短信发送成功 - 手机号: {Phone}, 耗时: {Duration}ms",
                        MaskPhoneNumber(message.PhoneNumber), (endTime - startTime).TotalMilliseconds);

                    return new SmsSendResult
                    {
                        Success = true,
                        MessageId = response.MessageId,
                        SentAt = endTime,
                        Provider = Name
                    };
                }
                else
                {
                    _logger.LogError(
                        "腾讯云短信发送失败 - 手机号: {Phone}, 错误: {Error}",
                        MaskPhoneNumber(message.PhoneNumber), response.ErrorMessage);

                    return new SmsSendResult
                    {
                        Success = false,
                        ErrorMessage = response.ErrorMessage,
                        SentAt = DateTime.UtcNow,
                        Provider = Name
                    };
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "腾讯云短信发送异常 - 手机号: {Phone}", MaskPhoneNumber(message.PhoneNumber));
                
                return new SmsSendResult
                {
                    Success = false,
                    ErrorMessage = ex.Message,
                    SentAt = DateTime.UtcNow,
                    Provider = Name
                };
            }
        }

        /// <summary>
        /// 使用模板发送短信
        /// </summary>
        public async Task<SmsSendResult> SendTemplateAsync(string templateId, Dictionary<string, string> templateParams, string phoneNumber, string? signName = null)
        {
            if (!IsConfigured)
            {
                return new SmsSendResult
                {
                    Success = false,
                    ErrorMessage = "腾讯云短信提供商未正确配置",
                    SentAt = DateTime.UtcNow,
                    Provider = Name
                };
            }

            try
            {
                var requestPayload = BuildSendTemplatePayload(templateId, templateParams, phoneNumber, signName);
                var requestUrl = string.Format(TENCENT_SMS_ENDPOINT, _settings.Region);
                
                var startTime = DateTime.UtcNow;
                var response = await SendRequest(requestUrl, "SendSms", requestPayload);
                var endTime = DateTime.UtcNow;

                if (response.Success)
                {
                    _logger.LogDebug(
                        "腾讯云模板短信发送成功 - 手机号: {Phone}, 模板: {Template}, 耗时: {Duration}ms",
                        MaskPhoneNumber(phoneNumber), templateId, (endTime - startTime).TotalMilliseconds);

                    return new SmsSendResult
                    {
                        Success = true,
                        MessageId = response.MessageId,
                        SentAt = endTime,
                        Provider = Name
                    };
                }
                else
                {
                    _logger.LogError(
                        "腾讯云模板短信发送失败 - 手机号: {Phone}, 错误: {Error}",
                        MaskPhoneNumber(phoneNumber), response.ErrorMessage);

                    return new SmsSendResult
                    {
                        Success = false,
                        ErrorMessage = response.ErrorMessage,
                        SentAt = DateTime.UtcNow,
                        Provider = Name
                    };
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "腾讯云模板短信发送异常 - 手机号: {Phone}", MaskPhoneNumber(phoneNumber));
                
                return new SmsSendResult
                {
                    Success = false,
                    ErrorMessage = ex.Message,
                    SentAt = DateTime.UtcNow,
                    Provider = Name
                };
            }
        }

        /// <summary>
        /// 测试连接
        /// </summary>
        public async Task<bool> TestConnectionAsync()
        {
            if (!IsConfigured)
            {
                _logger.LogWarning("腾讯云短信提供商未配置，跳过连接测试");
                return false;
            }

            try
            {
                // 使用查询短信发送状态的API来测试连接
                var payload = new
                {
                    SmsSdkAppId = _settings.SdkAppId,
                    SerialNo = "test-" + Guid.NewGuid().ToString("N")[..8],
                    PhoneNumberSet = new[] { "+8613800138000" }, // 测试号码
                    BeginTime = DateTimeOffset.UtcNow.AddDays(-1).ToUnixTimeSeconds(),
                    EndTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds(),
                    Limit = 1,
                    Offset = 0
                };

                var requestUrl = string.Format(TENCENT_SMS_ENDPOINT, _settings.Region);
                var response = await SendRequest(requestUrl, "PullSmsSendStatus", payload);

                if (response.Success || response.ErrorMessage?.Contains("InvalidParameter") == true)
                {
                    // 如果成功或者是参数错误（说明API可访问），都认为连接正常
                    _logger.LogInformation("腾讯云短信服务连接测试成功");
                    return true;
                }
                else
                {
                    _logger.LogError("腾讯云短信服务连接测试失败 - 错误: {Error}", response.ErrorMessage);
                    return false;
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "腾讯云短信服务连接测试异常");
                return false;
            }
        }

        /// <summary>
        /// 查询发送状态
        /// </summary>
        public async Task<SmsSendResult> QuerySendStatusAsync(string messageId)
        {
            if (!IsConfigured)
            {
                return new SmsSendResult
                {
                    Success = false,
                    ErrorMessage = "腾讯云短信提供商未正确配置",
                    SentAt = DateTime.UtcNow,
                    Provider = Name
                };
            }

            try
            {
                var payload = new
                {
                    SmsSdkAppId = _settings.SdkAppId,
                    SerialNo = messageId,
                    BeginTime = DateTimeOffset.UtcNow.AddDays(-7).ToUnixTimeSeconds(), // 查询最近7天
                    EndTime = DateTimeOffset.UtcNow.ToUnixTimeSeconds(),
                    Limit = 10,
                    Offset = 0
                };

                var requestUrl = string.Format(TENCENT_SMS_ENDPOINT, _settings.Region);
                var response = await SendRequest(requestUrl, "PullSmsSendStatus", payload);

                return new SmsSendResult
                {
                    Success = response.Success,
                    MessageId = messageId,
                    ErrorMessage = response.Success ? null : response.ErrorMessage,
                    SentAt = DateTime.UtcNow,
                    Provider = Name
                };
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "查询腾讯云短信发送状态异常 - 消息ID: {MessageId}", messageId);
                
                return new SmsSendResult
                {
                    Success = false,
                    ErrorMessage = ex.Message,
                    SentAt = DateTime.UtcNow,
                    Provider = Name
                };
            }
        }

        /// <summary>
        /// 构建发送普通短信的请求载荷
        /// </summary>
        private object BuildSendSmsPayload(SmsMessage message)
        {
            var phoneNumbers = new List<string>();
            
            // 格式化手机号码
            var phoneNumber = message.PhoneNumber;
            if (!phoneNumber.StartsWith("+"))
            {
                // 默认添加中国区号
                phoneNumber = "+86" + phoneNumber;
            }
            phoneNumbers.Add(phoneNumber);

            return new
            {
                PhoneNumberSet = phoneNumbers.ToArray(),
                SmsSdkAppId = _settings.SdkAppId,
                SignName = !string.IsNullOrEmpty(message.SignName) ? message.SignName : _settings.SignName,
                TemplateId = "0", // 纯文本短信使用模板ID 0
                TemplateParamSet = new[] { message.Content }
            };
        }

        /// <summary>
        /// 构建发送模板短信的请求载荷
        /// </summary>
        private object BuildSendTemplatePayload(string templateId, Dictionary<string, string> templateParams, string phoneNumber, string? signName)
        {
            var phoneNumbers = new List<string>();
            
            // 格式化手机号码
            if (!phoneNumber.StartsWith("+"))
            {
                // 默认添加中国区号
                phoneNumber = "+86" + phoneNumber;
            }
            phoneNumbers.Add(phoneNumber);

            // 将模板参数字典转换为数组（按顺序）
            var templateParamArray = templateParams?.Values.ToArray() ?? Array.Empty<string>();

            return new
            {
                PhoneNumberSet = phoneNumbers.ToArray(),
                SmsSdkAppId = _settings.SdkAppId,
                SignName = !string.IsNullOrEmpty(signName) ? signName : _settings.SignName,
                TemplateId = templateId,
                TemplateParamSet = templateParamArray
            };
        }

        /// <summary>
        /// 发送请求
        /// </summary>
        private async Task<TencentSmsResponse> SendRequest(string endpoint, string action, object payload)
        {
            try
            {
                var jsonPayload = JsonSerializer.Serialize(payload, new JsonSerializerOptions
                {
                    PropertyNamingPolicy = JsonNamingPolicy.CamelCase
                });

                // 构建请求头
                var headers = BuildHeaders(action, jsonPayload);
                
                var request = new HttpRequestMessage(HttpMethod.Post, endpoint)
                {
                    Content = new StringContent(jsonPayload, Encoding.UTF8, "application/json")
                };

                // 添加头信息
                foreach (var header in headers)
                {
                    if (header.Key == "Content-Type")
                        continue; // Content-Type已经在StringContent中设置
                    
                    request.Headers.TryAddWithoutValidation(header.Key, header.Value);
                }

                var response = await _httpClient.SendAsync(request);
                var responseContent = await response.Content.ReadAsStringAsync();

                if (response.IsSuccessStatusCode)
                {
                    var jsonDoc = JsonDocument.Parse(responseContent);
                    
                    if (jsonDoc.RootElement.TryGetProperty("Response", out var responseElement))
                    {
                        if (responseElement.TryGetProperty("SendStatusSet", out var sendStatusSet) && 
                            sendStatusSet.GetArrayLength() > 0)
                        {
                            var firstStatus = sendStatusSet[0];
                            var serialNo = firstStatus.TryGetProperty("SerialNo", out var serialNoElement)
                                ? serialNoElement.GetString()
                                : Guid.NewGuid().ToString();

                            var code = firstStatus.TryGetProperty("Code", out var codeElement)
                                ? codeElement.GetString()
                                : "Ok";

                            if (code == "Ok")
                            {
                                return new TencentSmsResponse
                                {
                                    Success = true,
                                    MessageId = serialNo
                                };
                            }
                            else
                            {
                                var message = firstStatus.TryGetProperty("Message", out var messageElement)
                                    ? messageElement.GetString()
                                    : "发送失败";

                                return new TencentSmsResponse
                                {
                                    Success = false,
                                    ErrorMessage = $"腾讯云错误 ({code}): {message}"
                                };
                            }
                        }
                        else if (responseElement.TryGetProperty("Error", out var error))
                        {
                            var code = error.TryGetProperty("Code", out var codeElement) 
                                ? codeElement.GetString() : "Unknown";
                            var message = error.TryGetProperty("Message", out var messageElement) 
                                ? messageElement.GetString() : "未知错误";
                            
                            return new TencentSmsResponse
                            {
                                Success = false,
                                ErrorMessage = $"腾讯云错误 ({code}): {message}"
                            };
                        }
                        else
                        {
                            // 其他情况认为成功
                            return new TencentSmsResponse
                            {
                                Success = true,
                                MessageId = Guid.NewGuid().ToString()
                            };
                        }
                    }
                }

                return new TencentSmsResponse
                {
                    Success = false,
                    ErrorMessage = $"HTTP错误: {response.StatusCode}, 响应: {responseContent}"
                };
            }
            catch (Exception ex)
            {
                return new TencentSmsResponse
                {
                    Success = false,
                    ErrorMessage = ex.Message
                };
            }
        }

        /// <summary>
        /// 构建请求头
        /// </summary>
        private Dictionary<string, string> BuildHeaders(string action, string payload)
        {
            var timestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString();
            var date = DateTime.UtcNow.ToString("yyyy-MM-dd");
            
            // 构建规范请求
            var canonicalUri = "/";
            var canonicalQueryString = "";
            var canonicalHeaders = $"content-type:application/json\nhost:sms.{_settings.Region}.tencentcloudapi.com\n";
            var signedHeaders = "content-type;host";
            var hashedPayload = SHA256Hash(payload);
            
            var canonicalRequest = $"POST\n{canonicalUri}\n{canonicalQueryString}\n{canonicalHeaders}\n{signedHeaders}\n{hashedPayload}";
            
            // 构建待签名字符串
            var algorithm = "TC3-HMAC-SHA256";
            var credentialScope = $"{date}/{SERVICE}/tc3_request";
            var hashedCanonicalRequest = SHA256Hash(canonicalRequest);
            var stringToSign = $"{algorithm}\n{timestamp}\n{credentialScope}\n{hashedCanonicalRequest}";
            
            // 计算签名
            var secretDate = HmacSHA256($"TC3{_settings.SecretKey}", date);
            var secretService = HmacSHA256(secretDate, SERVICE);
            var secretSigning = HmacSHA256(secretService, "tc3_request");
            var signature = HmacSHA256(secretSigning, stringToSign, true);
            
            // 构建Authorization头
            var authorization = $"{algorithm} Credential={_settings.SecretId}/{credentialScope}, SignedHeaders={signedHeaders}, Signature={signature}";

            return new Dictionary<string, string>
            {
                ["Authorization"] = authorization,
                ["Content-Type"] = "application/json",
                ["Host"] = $"sms.{_settings.Region}.tencentcloudapi.com",
                ["X-TC-Action"] = action,
                ["X-TC-Timestamp"] = timestamp,
                ["X-TC-Version"] = VERSION,
                ["X-TC-Region"] = _settings.Region
            };
        }

        /// <summary>
        /// SHA256哈希
        /// </summary>
        private static string SHA256Hash(string input)
        {
            using var sha256 = SHA256.Create();
            var hash = sha256.ComputeHash(Encoding.UTF8.GetBytes(input));
            return Convert.ToHexString(hash).ToLowerInvariant();
        }

        /// <summary>
        /// HMAC-SHA256
        /// </summary>
        private static byte[] HmacSHA256(byte[] key, string data)
        {
            using var hmac = new HMACSHA256(key);
            return hmac.ComputeHash(Encoding.UTF8.GetBytes(data));
        }

        /// <summary>
        /// HMAC-SHA256 with string key
        /// </summary>
        private static string HmacSHA256(string key, string data, bool hexResult = false)
        {
            using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(key));
            var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(data));
            return hexResult ? Convert.ToHexString(hash).ToLowerInvariant() : Convert.ToBase64String(hash);
        }

        /// <summary>
        /// 手机号码掩码处理
        /// </summary>
        private static string MaskPhoneNumber(string phoneNumber)
        {
            if (string.IsNullOrEmpty(phoneNumber) || phoneNumber.Length < 7)
                return phoneNumber;

            var start = phoneNumber.Substring(0, 3);
            var end = phoneNumber.Substring(phoneNumber.Length - 4);
            var mask = new string('*', phoneNumber.Length - 7);
            
            return start + mask + end;
        }

        /// <summary>
        /// 释放资源
        /// </summary>
        public void Dispose()
        {
            _httpClient?.Dispose();
        }
    }

    /// <summary>
    /// 腾讯云短信响应模型
    /// </summary>
    internal class TencentSmsResponse
    {
        public bool Success { get; set; }
        public string? MessageId { get; set; }
        public string? ErrorMessage { get; set; }
    }
}
